﻿using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Linq;
using System.Web;
using TCC.CMFlow.Models;

namespace TCC.CMFlow.Contexts
{
    public class DataContext : IdentityDbContext<Usuario>
    {
        public DataContext()
            : base("CMFlowConnection")
        {
        }
        
        public DbSet<MenuSistema> MenuSistema { get; set; }
        public DbSet<ModuloSistema> ModuloSistemas { get; set; }
        public DbSet<Permissao> Permissao { get; set; }
        public DbSet<PerfilAcesso> PerfilAcesso { get; set; }
        public DbSet<PerfilAcessoConfiguracao> PerfilAcessoConfiguracao { get; set; }
        public DbSet<GrupoAprovacao> GrupoAprovacao { get; set; }
        public DbSet<CategoriaWorkflow> CategoriaWorkflow { get; set; }
        public DbSet<CategoriaGrupo> CategoriaGrupos { get; set; }
        public DbSet<CategoriaWebService> CategoriaWebService { get; set; }
        public DbSet<CategoriaWebServiceAtributo> CategoriaWebServiceAtributos { get; set; }
        public DbSet<Workflow> Workflow { get; set; }
        public DbSet<WorkflowDado> WorkflowDado { get; set; }
        public DbSet<WorkflowAprovacao> WorkflowAprovacao { get; set; }
        public DbSet<WorkflowAprovacaoDado> WorkflowAprovacaoDado { get; set; }
        public DbSet<LogSistema> LogSistema { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
            //modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<Usuario>()
                .ToTable("Usuarios", "dbo");
            modelBuilder.Entity<IdentityUser>()
                .ToTable("Usuarios", "dbo");
            modelBuilder.Entity<IdentityRole>()
                .ToTable("Roles", "dbo");
            modelBuilder.Entity<IdentityUserRole>()
                .ToTable("Usuarios Role", "dbo");
            modelBuilder.Entity<IdentityUserLogin>()
                .ToTable("Usuarios Login", "dbo");
            modelBuilder.Entity<IdentityUserClaim>()
                .ToTable("Usuarios Claim", "dbo");
            modelBuilder.Entity<IdentityUserClaim>()
                .ToTable("Usuarios Claim", "dbo");

            modelBuilder.Entity<Usuario>()
                        .HasKey(i => i.Id);

            modelBuilder.Entity<Usuario>()
                        .HasKey(i => i.Codigo)
                        .Property(i => i.Codigo).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

            modelBuilder.Entity<Usuario>()
                        .HasRequired<PerfilAcesso>(u => u.PerfilAcesso);

            modelBuilder.Entity<MenuSistema>()
                        .HasMany(c => c.ModulosSistema).WithOptional(i => i.MenuSistema)
                        .HasForeignKey(m => m.MenuSistemaID);

            //modelBuilder.Entity<PerfilAcesso>()
            //            .HasMany(c => c.MenusSistema).WithMany(i => i.PerfisAcesso)
            //            .Map(t => t.MapLeftKey("PerfilAcessoID")
            //            .MapRightKey("MenuSistemaID")
            //            .ToTable("PerfilAcessoMenu"));

            modelBuilder.Entity<PerfilAcessoConfiguracao>()
                        .HasMany(c => c.Permissoes).WithMany(p => p.PerfilAcessoConfiguracoes)
                        .Map(m => m.MapLeftKey("ConfiguracaoID")
                        .MapRightKey("PermissaoID")
                        .ToTable("PerfilAcessoPermissao"));

            //modelBuilder.Entity<PerfilAcessoConfiguracao>()
            //            .HasKey(c => new { c.PerfilAcessoID, c.ModuloSistemaID });

            modelBuilder.Entity<GrupoAprovacao>()
                        .HasMany(c => c.Usuarios).WithMany(i => i.GruposAprovacao)
                        .Map(t => t.MapLeftKey("GrupoAprovacaoID")
                        .MapRightKey("UsuarioID")
                        .ToTable("GrupoUsuario"));

            modelBuilder.Entity<CategoriaGrupo>()
                        .HasKey(c => new { c.CategoriaWorkflowID, c.GrupoAprovacaoID});

            modelBuilder.Entity<CategoriaWorkflow>()
                        .HasMany(c => c.CategoriaGrupos)
                        .WithRequired()
                        .HasForeignKey(cg => cg.CategoriaWorkflowID);

            modelBuilder.Entity<GrupoAprovacao>()
                        .HasMany(g => g.GrupoCategorias)
                        .WithRequired()
                        .HasForeignKey(cg => cg.GrupoAprovacaoID);

            modelBuilder.Entity<CategoriaGrupo>()
                        .HasMany(c => c.Usuarios)
                        .WithMany(u => u.CategoriasGrupo)
                        .Map(m => m.MapLeftKey("CategoriaWorkflowID", "GrupoAprovacaoID")
                        .MapRightKey("UsuarioID")
                        .ToTable("CategoriaGrupoUsuario"));

            modelBuilder.Entity<CategoriaWebService>()
                        .HasKey(k => k.CategoriaWorkflowID);

            modelBuilder.Entity<CategoriaWorkflow>()
                        .HasOptional<CategoriaWebService>(c => c.CategoriaWebService)
                        .WithRequired(w => w.CategoriaWorkflow);

            modelBuilder.Entity<CategoriaWebService>()
                        .HasMany(c => c.CategoriaWebServiceAtributos)
                        .WithRequired(a => a.CategoriaWebService)
                        .HasForeignKey(f => f.CategoriaWorkflowID);

            modelBuilder.Entity<CategoriaWebServiceAtributo>()
                        .HasKey(c => new { c.ID, CategoriaWorkflowID = c.CategoriaWorkflowID })
                        .Property(i => i.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

            modelBuilder.Entity<CategoriaWebServiceAtributo>()
                        .HasOptional(c => c.Parent)
                        .WithMany(c => c.Childrens)
                        .HasForeignKey(c => new { c.ParentID, CategoriaWorkflowID = c.CategoriaWorkflowID });

            modelBuilder.Entity<Workflow>()
                        .HasRequired(w => w.CategoriaWorkflow)
                        .WithMany(c => c.Workflows)
                        .HasForeignKey(c => c.CategoriaWorkflowID);

            modelBuilder.Entity<Workflow>()
                        .HasMany(w => w.Dados)
                        .WithRequired(d => d.Workflow)
                        .HasForeignKey(d => d.WorkflowID);

            modelBuilder.Entity<WorkflowDado>()
                        .HasKey(c => new { c.ID, WorkflowID = c.WorkflowID })
                        .Property(i => i.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

            modelBuilder.Entity<WorkflowDado>()
                        .HasOptional(d => d.Parent)
                        .WithMany(d => d.Childrens)
                        .HasForeignKey(d => new { d.ParentID, WorkflowID = d.WorkflowID });

            modelBuilder.Entity<Workflow>()
                        .HasMany(w => w.Aprovacoes)
                        .WithRequired(d => d.Workflow)
                        .HasForeignKey(d => d.WorkflowID);

            modelBuilder.Entity<WorkflowAprovacao>()
                        .HasOptional(a => a.Usuario)
                        .WithMany(u => u.WorkflowAprovacoes)
                        .HasForeignKey(u => u.UsuarioID);

            modelBuilder.Entity<WorkflowAprovacao>()
                        .HasMany(a => a.Dados)
                        .WithRequired(d => d.WorkflowAprovacao)
                        .HasForeignKey(d => d.WorkflowAprovacaoID);

            modelBuilder.Entity<LogSistema>()
                        .HasOptional(l => l.Usuario)
                        .WithMany(u => u.LogSistema)
                        .HasForeignKey(k => k.UsuarioID);

            modelBuilder.Entity<LogSistema>()
                        .HasOptional(l => l.Modulo)
                        .WithMany(m => m.Logs)
                        .HasForeignKey(k => k.ModuloID);
        }
    }
}